# _*_coding:utf-8_*_
# 编辑用户：IT
# 文件名称：calculate
# 开发时间：2024/5/10 19:09
import torch
import numpy as np
import statistics
from medpy.metric.binary import hd95


# 计算Dice系数
def dice_calculate(x, y):
    smooth = 1e-5  # 极小值,防止零除
    num = x.size(0)
    m1 = x.reshape(num, -1)
    m2 = y.reshape(num, -1)
    # 计算交集
    intersection = (m1 * m2).sum()
    # 计算并集
    unionset = m1.sum() + m2.sum()
    dice = (2. * intersection) / (unionset + smooth)
    return dice


# 计算jaccard系数
def jaccard_calculate(x, y):
    smooth = 1e-7
    num = x.size(0)
    m1 = x.reshape(num, -1)
    m2 = y.reshape(num, -1)
    # 计算交集
    intersection = (m1 * m2).sum()
    # 计算并集
    unionset = m1.sum() + m2.sum() - intersection
    jaccard = (1. * intersection) / (unionset + smooth)
    return jaccard


# 计算PPV
def ppv_calculate(x, y):
    smooth = 1e-10
    num = x.size(0)
    m1 = x.reshape(num, -1)
    m2 = y.reshape(num, -1)
    # 计算交集,即TP
    tp = (m1 * m2).sum()
    # 计算TP+TN
    tn = ((1 - m2) * m1).sum()
    # PPV = TP/(TP + TN)
    return tp / (tp + tn + smooth)


# 计算95%豪斯多夫距离
def hausdorff_distance(x, y):
    device_cpu = torch.device('cpu')  # 驱动为CPU
    # 定义预测结果和真实标记数组
    x = x.to(device_cpu).numpy().astype(int)
    y = y.to(device_cpu).numpy().astype(int)
    # 计算95%豪斯多夫距离
    if x.sum() == 0 or y.sum() == 0:
        return 0.0
    else:
        hausdorff_distance95 = hd95(x, y)
        return hausdorff_distance95


# 计算MSE
def MSE_calculate(x, y):
    d, b, l = x.shape
    array = (x - y)**2
    MSE = array.sum()/(d * b * l)
    return MSE


# 计算所有的评估指标
def calculate_all(x, y):
    dice = dice_calculate(x, y)
    jaccard = jaccard_calculate(x, y)
    ppv = ppv_calculate(x, y)
    MSE = MSE_calculate(x, y)
    hd_95 = hausdorff_distance(x, y)
    return dice, jaccard, ppv, MSE, hd_95


# 分割海马体为左右两部分
def hippocampus_left_right(predicted):
    new_left = predicted.clone()  # 创建predicted的张量副本
    new_right = predicted.clone()  # 创建predicted的张量副本
    new_left = torch.where(new_left == 1, new_left, torch.zeros_like(new_left))
    new_right = torch.where(new_right == 2, torch.ones_like(new_right), torch.zeros_like(new_right))
    return new_left, new_right


# 分割海马体为2的标签改为1
def hippocampus_2_to_1(predicted):
    new = predicted.clone()  # 创建predicted的张量副本
    new = new.clamp(max=1)
    return new


# 计算张量的平均值和标准差
def average_standard(torch_list):
    average = torch_list.mean()
    standard_deviation = torch_list.std()
    return average, standard_deviation
